﻿using System;
using System.Collections.Generic;

namespace SCommunicator
{
    /// <summary>
    /// 串口通讯细节实现类
    /// </summary>
    public class SComm
    {
        private readonly List<byte> _dataList = new List<byte>();
        private readonly List<RawHandler> _listRawHandler = new List<RawHandler>();

        /// <summary>
        /// 在串口接收到字节数据时候触发的事件
        /// </summary>
        public event RawHandler OnRaw;

        /// <summary>
        /// 在串口接收到字节数据时候触发的事件委托
        /// </summary>
        /// <param name="bytes"></param>
        public delegate void RawHandler(byte[] bytes);

        /// <summary>
        /// 实例化
        /// </summary>
        /// <param name="comm">串口配置</param>
        /// <param name="result">消息解析方法集合</param>
        public SComm(ICommunication comm, IAnalyzerCollection result)
        {
            if (comm == null)
            {
                throw new NullReferenceException("通讯模块没有引用对象");
            }
            this.Comm = comm;
            this.Results = result;
            this.Comm.DataReceived += new DataReceivedHandler(this.CommDataReceived);
            this.ReadBufferSize = 0x800;
        }

        private void CommDataReceived(ICommunication icommunication)
        {
            int bytesToRead = icommunication.BytesToRead;
            var buffer = new byte[bytesToRead];
            icommunication.Read(buffer, 0, bytesToRead);
            if (this._dataList.Count > this.ReadBufferSize)
            {
                this._dataList.Clear();
            }
            this._dataList.AddRange(buffer);
            if (this.OnRaw != null)
            {
                this._listRawHandler.Clear();
                Delegate[] invocationList = this.OnRaw.GetInvocationList();
                int index = 0;
                while (true)
                {
                    if (index >= invocationList.Length)
                    {
                        break;
                    }
                    RawHandler item = (RawHandler) invocationList[index];
                    try
                    {
                        item(buffer);
                    }
                    catch (InvalidOperationException)
                    {
                        this._listRawHandler.Add(item);
                    }
                    index++;
                }
                foreach (RawHandler handler2 in this._listRawHandler)
                {
                    this.OnRaw = (RawHandler)Delegate.Remove(this.OnRaw, handler2);
                }
            }
            foreach (IAnalyzer analyzer in this.Results)
            {
                analyzer.SearchBuffer(this._dataList);
                if (analyzer.Raw.Length > 0)
                {
                    analyzer.Analyze();
                    analyzer.Raw = new byte[0];
                }
            }
        }

        /// <summary>
        /// 串口对象
        /// </summary>
        public ICommunication Comm { get; set; }

        /// <summary>
        /// 设置或获取缓冲区大小
        /// </summary>
        public int ReadBufferSize { get; set; }

        /// <summary>
        /// 消息解析方法集合
        /// </summary>
        public IAnalyzerCollection Results { get; set; }
    }
}
